#include "contacts.h"

void InitContacts(PeoCont* con){
    assert(con);
    con->sz = 0;
    memset(con->data, 0, sizeof(con->data));
}

void AddContacts(PeoCont* con){
    assert(con);
    if(con->sz == MAX){
        printf("通讯录已满，无法添加！\n");
        return;
    }
        
    printf("请输入联系人的姓名:>");
    scanf("%s", con->data[con->sz].name);
    printf("请输入联系人的年龄:>");
    scanf("%d", &con->data[con->sz].age);   
    printf("请输入联系人的性别:>");
    scanf("%s", con->data[con->sz].sex);    
    printf("请输入联系人的地址:>");
    scanf("%s", con->data[con->sz].addr);   
    printf("请输入联系人的电话:>");
    scanf("%s", con->data[con->sz].tele); 
    con->sz++;
    printf("添加成功！\n");
}

void ShowContacts(const PeoCont* con){
    assert(con);
    printf("%-20s\t%-5s\t\t%-5s\t\t%-30s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
    if(con->sz == 0){
        printf("通讯录为空，无法输出！\n");
        return;
    }
    for(int i = 0; i < con->sz; i++){
        printf("%-20s\t%-3d\t\t%-5s\t\t%-30s%-12s\n", con->data[i].name, 
                                        con->data[i].age,
                                        con->data[i].sex,
                                        con->data[i].addr, 
                                        con->data[i].tele);
    }
}

//在通讯录中查找联系人
static int  FindContacts(const PeoCont* con){
    assert(con);
    char name[NAME_MAX];
    printf("请输入联系人的姓名:>");
    scanf("%s", name);
    for(int i = 0; i < con->sz; i++){
        if(strcmp(con->data[i].name, name) == 0){
            return i;
        }
    }
    return -1;
}

void DelContacts(PeoCont* con){
    assert(con);
    int pos = FindContacts(con);
    if(pos == -1){
        printf("输入的联系人不存在\n");
        return;
    }
    else{
        for(int i = pos; i < con->sz - 1; i++){
            con->data[i] = con->data[i + 1];
        }
        con->sz--;
        printf("删除成功！\n");
    }
}

void SearchContacts(const PeoCont* con){
    assert(con);
    int pos = FindContacts(con);
    if(pos == -1){
        printf("查找的联系人不存在！\n");
    }
    else{
        printf("%-20s\t%-5s\t\t%-5s\t\t%-30s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
        printf("%-20s\t%-3d\t\t%-5s\t\t%-30s%-12s\n", con->data[pos].name, 
                                        con->data[pos].age,
                                        con->data[pos].sex,
                                        con->data[pos].addr, 
                                        con->data[pos].tele);
    }
}

void ModifyContacts(PeoCont* con){
    assert(con);
    int pos = FindContacts(con);
    if( pos == -1){
        printf("查找的联系人不存在！");
        return;
    }
    else {
        printf("请输入联系人的姓名:>");
        scanf("%s", con->data[pos].name);
        printf("请输入联系人的年龄:>");
        scanf("%d", &con->data[pos].age);   
        printf("请输入联系人的性别:>");
        scanf("%s", con->data[pos].sex);    
        printf("请输入联系人的地址:>");
        scanf("%s", con->data[pos].addr);   
        printf("请输入联系人的电话:>");
        scanf("%s", con->data[pos].tele);
    }
    printf("修改成功！\n");
}


//以char类型指针，每次交换一个字节的数据，确保能交换任意类型数据
static void Swap(char* elem1, char* elem2, size_t width){
    size_t i = 0;
    for(i = 0; i < width; i++){
        char tmp = *(elem1 + i);
        *(elem1 + i) = *(elem2 + i);
        *(elem2 + i) = tmp;
    }
}

//通过联系人的姓名进行排序
static int PeoContByName_cmp(const void* elem1, const void* elem2){
    return strcmp(((PeoContacts*)elem1)->name,((PeoContacts*)elem2)->name);
}

//利用冒泡排序模拟qsort库函数对联系人进行排序
static void bubblesort(void* base, size_t sz, size_t width, int (*cmp)(void* ,void* )){
    size_t i = 0;
    for(i = 0; i < sz; i++){
        for(size_t j = 0; j < sz - 1 - i;j++){
            if(cmp((char*)base + j * width,(char *)base + (j + 1) * width) > 0)
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
        }
    }
}


void SortContacts(PeoCont* con){
    assert(con);
    bubblesort(con->data, con->sz, sizeof(con->data[0]), (void*) PeoContByName_cmp);
    printf("根据联系人的姓名排序成功！\n");
} //遇到问题:段错误 (核心已转储)。现已解决，数组规模传的有问题，不应该用sizeof(con->data),用con->sz且规模不大时这个就不会报错
